home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1995 May / cd Ware (Juegos) Epimundo.iso / DOS / C / COP.ZIP / COP.CFM < prev    next >
Encoding:
Text File  |  1992-07-21  |  15.7 KB  |  641 lines

  1. /*
  2.     cop.cfm -- C Object Programming: object
  3.         source template.
  4.  
  5.     (C) Copyright 1992  John W. Small
  6.     All rights reserved
  7.  
  8.     PSW / Power SoftWare
  9.     P.O. Box 10072
  10.     McLean, Virginia 22102 8072 USA
  11.     Voice: (703) 759-3838
  12.  
  13.     Always edit a cloned copy of this file.  With
  14.     the case-sensitive flag set and word-only
  15.     flag reset ...
  16.     
  17.     Find and Replace    with something like
  18.     
  19.       structFileName        foobar
  20.       structType            foobar
  21.       structFncPrefix        FB
  22.       
  23.     Edit the remaining text to fully declare your 
  24.     new object.  This file is setup to suggest 
  25.     that your new object inherits three previously 
  26.     declared objects (base1, base2, and base3), 
  27.     the first of which has inherited two more 
  28.     objects.  The third is a virtual base class. 
  29.     All the objects in the hierarchy supposedly 
  30.     have vFt's (Virtual Function Tables) that have
  31.     one or more vF's overridden by the object being 
  32.     declared.  Simply delete those items not 
  33.     pertaining to the new object you're declaring. 
  34.     You should find enough structure here to guide 
  35.     you in expanding this boiler plate for more 
  36.     complicated hierarchies if need be.
  37.  
  38.     Find and replace    with something like
  39.     
  40.       base1FileName            strawber
  41.       base1StructType        Strawberry
  42.       base1StructFncPrefix        SWB
  43.     
  44.     or delete those lines containing unnecessary 
  45.     items.  Complete the find and replace process 
  46.     for base11, base12, base2, and base3 and delete
  47.     any comments you find inappropriate such as 
  48.     this one.
  49. */
  50.  
  51.  
  52. /*
  53.     structFileName.c -- COP object source
  54. */
  55.  
  56.  
  57. #include "structFileName.h"
  58.  
  59.  
  60. /*
  61.     See cop.hfm notes on implicit
  62.     type casting chains.
  63. */
  64. polyBaseThiS_0_def(structFncPrefix,
  65.     base1StructType,structType)
  66.     /* No semicolon needed! */
  67.  
  68.  
  69. /*  Define structType's static data  */
  70.  
  71. static_def(structType);
  72.  
  73.  
  74.  
  75. /*  Define structType's default vFt for new vF's  */
  76.  
  77. vFt_def(structType,structType)  =  {
  78.  
  79.     vF_value(structFncPrefix,structFncPrefix,
  80.         dummyVf),
  81.     vF_value(structFncPrefix,structFncPrefix,
  82.         destruct)
  83. /*
  84.     vFts are assumed to be initialized to 
  85.     valid vFs, i.e. no checks are made by 
  86.     the vf_runTimeBind() macro!
  87. */
  88.  
  89. };
  90.  
  91.  
  92. /*
  93.     Define vf's for structType's default vFt.
  94.     
  95.     In practice you'll find it easy to copy the 
  96.     vf_decl()s from the header file and edit them
  97.     to read vf_def().
  98. */
  99.  
  100.  
  101. vf_def(void,structFncPrefix,structFncPrefix,
  102.     dummyVf,(structType * thiS, ...))
  103. {
  104.     ???
  105. }
  106.  
  107. vf_def(void,structFncPrefix,structFncPrefix,
  108.     destruct,(structType * thiS, unsigned nobj,
  109.     int malloced))
  110. {
  111.     struct_destruct(structFncPrefix,thiS,nobj,
  112.         malloced);
  113.     
  114. /*
  115.     When overriding this vf for a derived struct 
  116.     besure to call the derived struct's 
  117.     "struct_destruct".  Remember "thiS" must be 
  118.     type cast to the overriding struct's thiS!
  119.     That's because destruction begins at the last
  120.     derived class and works back.
  121.     
  122.     struct_destuct(overridingStructFncPrefix,
  123.       structFncPrefix_overridingStructTypeThiS
  124.       (thiS),nobj,malloced);
  125. */
  126.  
  127. }
  128.  
  129.  
  130.  
  131. /*
  132.     Define structType's overriding vFt's for all
  133.     base structs within the inherited hierarchy
  134.     having vf's overridden at StructName level.
  135. */
  136.  
  137.  
  138. /*
  139.     It's easiest if you copy the complete vFt_def
  140.     and edit as it reads below.  That way non 
  141.     overridden vf's can be left unmodified and 
  142.     the tracking of overrides at various levels
  143.     is thus not a problem.
  144. */
  145.  
  146. vFt_def(structType,base1StructType)  =  {
  147.  
  148. /*  override a base1 vf  */
  149.  
  150.     vF_value(structFncPrefix,
  151.         base1StructFncPrefix,vfbase1);
  152.  
  153. /*
  154.     Perhaps not all vfs are overridden at this 
  155.     level but a vF must be specified for each 
  156.     entry in the table!  In such cases assign the 
  157.     non overridden value to the table.  Notice 
  158.     that only overridden vfs are defined below 
  159.     since the non overridden have already been 
  160.     defined elsewhere.
  161. */
  162.  
  163. /*  This vf is not overridden!  */
  164.  
  165.     vF_value(base1StructFncPrefix,
  166.         base1StructFncPrefix,???);
  167.  
  168. };
  169.  
  170.  
  171. /*
  172.     Again, copying vf_decl()s from the header and 
  173.     editing them to read vf_def()s saves a great 
  174.     deal of time here!
  175. */
  176.  
  177. vf_def(base1StructType *,structFncPrefix,base1StructFncPrefix,
  178.     vfbase1,(base1StructType * thiS, ...))
  179. {
  180. /*
  181.     For overriding vfs remember to use the type 
  182.     cast macros for "thiS", i.e.
  183.     
  184.     structType * dThiS =
  185.       base1StructFncPrefix_structTypeThiS(thiS);
  186.       
  187.     Then use "dThiS" to access data in the derived 
  188.     struct!
  189. */
  190.     ???
  191.     return thiS;
  192.  
  193. /*
  194.     If you need a virtual function to return a
  195.     pointer to the current derived level code
  196.     simply return dThiS instead:
  197.     
  198.        return (base1StructType *) dThiS;
  199.     
  200.     
  201.     Be sure to typecast it back to (structType *)
  202.     before using.  (Note: this is not yet a C++ 
  203.     feature.)
  204. */
  205.  
  206. }
  207.  
  208.  
  209. vFt_def(structType,base11StructType)  =  {
  210.  
  211.     vF_value(structFncPrefix,
  212.         base11StructFncPrefix,vfbase11);
  213.  
  214. /*
  215.     Here's an example of a base11 vf overridden at
  216.     the base1 level but not at the current level.
  217.     If you copied the complete vFt_def() from
  218.     base1 and edited the overridden vf's at the
  219.     structType level, it requires no thought as
  220.     to what might have been overridden at 
  221.     intermediate levels.  If you go back and edit
  222.     the intermediate level overrides then your 
  223.     maintenance task is going to require some 
  224.     work.  Hay, what can I say? - this isn't C++!
  225. */
  226.  
  227.     vF_value(base1StructType,
  228.         base11StructFncPrefix,???);
  229.  
  230. };
  231.  
  232. vf_def(void,structFncPrefix,base11StructFncPrefix,
  233.     vfbase11,(base11StructType * thiS, ...))
  234. {
  235.     ???
  236. }
  237.  
  238.  
  239. vFt_def(structType,base12StructType)  =  {
  240.     vF_value(structFncPrefix,
  241.         base12StructType,vfbase12);
  242.     vF_value(base12StructType,
  243.         base12StructType,???);
  244. };
  245.  
  246. vf_def(int,structFncPrefix,base12StructFncPrefix,
  247.     vfbase12,(base12StructType * thiS, ...))
  248. {
  249.     ???
  250.     return ???;
  251. }
  252.  
  253.  
  254. vFt_def(structType,base2StructType)  =  {
  255.     vF_value(structFncPrefix,
  256.         base2StructFncPrefix,vfbase2);
  257.     vF_value(base2StructFncPrefix,
  258.         base2StructFncPrefix,???);
  259. };
  260.  
  261. vf_def(int,structFncPrefix,base2StructFncPrefix,
  262.     vfbase2,(base2StructType * thiS, ...))
  263. {
  264.     ???
  265.     return ???;
  266. }
  267.  
  268. vFt_def(structType,base3StructType)  =  {
  269.     vF_value(structFncPrefix,
  270.         base3StructFncPrefix,vfbase3);
  271. };
  272.  
  273. vf_def(int,structFncPrefix,base3StructFncPrefix,
  274.     vfbase3,(base3StructType * thiS, ...))
  275. {
  276.     ???
  277.     return ???;
  278. }
  279.  
  280.  
  281. /*
  282.     Define structType's protected constructors 
  283.     and destructors.  Be sure to follow this 
  284.     format even for simple objects to insure that
  285.     they are extensible -- you'll begin to see the
  286.     reasoning once your hierarchies begin to grow.
  287. */
  288.  
  289. struct_initVFTs_def(structFncPrefix,
  290.     (structType * thiS, 
  291.     void * descendanT_0
  292.     , vFT_0_decl(structType)
  293. /*
  294.     All base structs with vFTs need    to be 
  295.     initialized thus require their specific formal 
  296.     parameter.  A null pointer when passed as a 
  297.     actual parameter indicates to use the default 
  298.     vFT in question.
  299. */
  300.     , vFT_0_decl(base1StructType)
  301.     , vFT_0_decl(base11StructType)
  302.     , vFT_0_decl(base12StructType)
  303.     , vFT_0_decl(base2StructType)
  304.     , vbThiS_decl(base3StructType)
  305.     , vbDescendanT_0_decl(base3StructType)
  306.     , vFT_0_decl(base3StructType)
  307.     ))
  308. /* Be sure to have enough closing parentheses above! */
  309. {
  310.  
  311. /*
  312.     Polymorphic structs must call poly_assign!
  313. */
  314.     poly_assign(thiS,descendanT_0);
  315.  
  316. /*
  317.     Assign vFT at this level if appropriate.
  318. */
  319.     vFT_assign(structType,structType,
  320.         thiS,vFT_0_name(structType));
  321.  
  322. /*
  323.     Call only directly inherited base struct
  324.     struct_initVFTs() macros!  Notice that the
  325.     "thiS" pointers are type cast to their
  326.     respective base struct pointers and that the
  327.     descendanT_0 pointers are set in the base
  328.     structs to point to the current level struct!
  329.     When each struct in a hierarchy follows this
  330.     convention, the necessary chaining is
  331.     automatically established for the type cast
  332.     macros converting from base to derived
  333.     structs.  These are the type casts necessary
  334.     within overriding virtual functions!
  335. */
  336.     struct_initVFTs(base1StructFncPrefix,
  337.         (structFncPrefix_base1StructTypeThiS
  338.         (thiS), (void *) thiS
  339.         , vFT_0_name(base1StructType)
  340.         , vFT_0_name(base11StructType)
  341.         , vFT_0_name(base12StructType)
  342.         ));
  343. /* Be sure to have enough closing parentheses above! */
  344.     struct_initVFTs(base2StructFncPrefix,
  345.         (structFncPrefix_base2StructTypeThiS
  346.         (thiS), (void *) thiS
  347.         , vFT_0_name(base2StructType)
  348.         ));
  349. /* Be sure to have enough closing parentheses above! */
  350.  
  351. /*
  352.     If base2 branch of the hierarchy hadn't been
  353.     polymorphic the call above would have been:
  354.  
  355.     struct_initVFTs(base2StructFncPrefix,NO_VFTs);
  356. */
  357.  
  358. /*
  359.     Remember base3 has no way to know that it's
  360.     a virtual base structure.  Notice that the
  361.     virtual base's descendanT pointer points to
  362.     either is directly derived node or preferribly
  363.     to the virtual base host structure at the
  364.     corresponding casing structure joint.
  365. */
  366.     struct_initVFTs(base3StructFncPrefix,
  367.         ( vbThiS_name(base3StructType)
  368.         , vbDescendant_value(base3StructType,
  369.             thiS)
  370.         , vFT_0_name(base3StructType)
  371.         ));
  372. /* Be sure to have enough closing parentheses above! */
  373.  
  374. }
  375.  
  376. /*
  377.     The following protected constructor is called
  378.     with nobj == 1 by derived structure
  379.     constructors or with nobj >= 1 to instanciate
  380.     an instance or vector of instances of the
  381.     current level structure.
  382. */
  383.  
  384.  
  385. struct_init_def(structType,structFncPrefix,_,
  386.     (structType * thiS_0
  387.         , unsigned nobj
  388.         , vbThiS_decl(base3StructType)
  389.         , ... initializers
  390.     ))
  391. {
  392.   unsigned i, fail;
  393.   int malloced = 0;
  394.  
  395.   if (!nobj)
  396.     return (structType *)0;
  397.   if (!thiS_0) if ((thiS_0 = (structType *)
  398.     structFncPrefix_malloc(nobj))
  399.     == (structType *)0)
  400.     return (structType *)0;
  401.   else
  402.     malloced = 1;
  403.   for (i = fail = 0; i < nobj; i++)  {
  404.  
  405.  
  406.   /*
  407.     Initialize all base structs first,
  408.     then initialize vFTs, etc.,
  409.     then initialize structType data.
  410.   */
  411.  
  412.     if (!struct_init(base1StructFncPrefix,
  413.       base1StructFncOvrLdSuffix,
  414.       (structFncPrefix_base1StructTypeThiS(&thiS_0[i])
  415.       ,1, ... initializers)))  {
  416.       fail = 1;
  417.       break;
  418.     }
  419.     if (!struct_init(base2StructFncPrefix,
  420.       base2StructFncOvrLdSuffix,
  421.       (structFncPrefix_base2StructTypeThiS(&thiS_0[i])
  422.       ,1, ... initializers)))  {
  423.       /* leave all bases at this index destructed */
  424.       struct_destruct(base1StructFncPrefix,
  425.         structFncPrefix_base1StructTypeThiS
  426.     (&thiS_0[i]),1,0);
  427. /*
  428.     Remember struct_destruct() DOESN'T take a 
  429.     parenthesized actualParams argument!
  430. */
  431.       fail = 1;
  432.       break;
  433.     }
  434.     if (!struct_init(base3StructFncPrefix,
  435.       base3StructFncOvrLdSuffix,
  436.       (structFncPrefix_base3StructTypeThiS(&thiS_0[i])
  437.       ,1, vbThiS_name(base3StructType)
  438.       , ... initializers)))  {
  439.       /* leave all bases at this index destructed */
  440.       struct_destruct(base2StructFncPrefix,
  441.         structFncPrefix_base2StructTypeThiS
  442.     (&thiS_0[i]),1,0);
  443. /*
  444.     Remember struct_destruct() DOESN'T take a 
  445.     parenthesized actualParams argument!
  446. */
  447.       struct_destruct(base1StructFncPrefix,
  448.         structFncPrefix_base1StructTypeThiS
  449.     (&thiS_0[i]),1,0);
  450. /*
  451.     Remember struct_destruct() DOESN'T take a 
  452.     parenthesized actualParams argument!
  453. */
  454.       fail = 1;
  455.       break;
  456.     }
  457.  
  458.  
  459.     /* setup default vFT for structType level */
  460.  
  461.     struct_initVFTs(structFncPrefix
  462.       ,(&thiS_0[i], (void *)0
  463.       , vFT0(structType)
  464.       , vFT0(base1StructType)
  465.     /* or vFT_value(structType,base1StructType) */
  466.       , vFT0(base11StructType)
  467.     /* or vFT_value(structType,base11StructType) */
  468.       , vFT0(base12StructType)
  469.     /* or vFT_value(structType,base12StructType) */
  470.       , vFT0(base2StructType)
  471.     /* or vFT_value(structType,base2StructType) */
  472.       , vbThiS_name(base3StructType)
  473.       , vbDescendanT_value(base3StructType,thiS)
  474.       , vFT0(base3StructType)
  475.     /* or vFT_value(structType,base3StructType) */
  476.     ));
  477. /* Be sure to have enough closing parentheses above! */
  478.  
  479.     /* initialize structType data level */
  480.  
  481.     thiS_0[i].??? = ???;
  482.     if (current level initialization fails)  {
  483.       /* destruct all data at this level and index */
  484.       ???
  485.       /* destruct all bases at this index */
  486.       struct_destruct(base3StructFncPrefix,
  487.         structFncPrefix_base3StructTypeThiS
  488.     (&thiS_0[i]),1,0);
  489. /*
  490.     Remember struct_destruct() DOESN'T take a 
  491.     parenthesized actualParams argument!
  492. */
  493.       struct_destruct(base2StructFncPrefix,
  494.         structFncPrefix_base2StructTypeThiS
  495.     (&thiS_0[i]),1,0);
  496. /*
  497.     Remember struct_destruct() DOESN'T take a 
  498.     parenthesized actualParams argument!
  499. */
  500.       struct_destruct(base1StructFncPrefix,
  501.         structFncPrefix_base1StructTypeThiS
  502.     (&thiS_0[i]),1,0);
  503. /*
  504.     Remember struct_destruct() DOESN'T take a 
  505.     parenthesized actualParams argument!
  506. */
  507.       fail = 1;
  508.       break;
  509.     }
  510.  
  511.   }  /* for */
  512.  
  513.   if (fail)  {
  514.     /*
  515.     All indices >= "i" have already been destructed
  516.     as required.  Indices i-1 to 0 are now
  517.     destructed via the destructor since we're
  518.     inside the constructor of the instance level if
  519.     i > 0.  Remember that if this is an
  520.     intermediate constructor call that i == 0
  521.     and malloced == 0 always so no further
  522.     processing is required at this level and NULL
  523.     is returned to the calling level constructor.
  524.     */
  525.     if (i)
  526.       struct_destruct(structFncPrefix,thiS_0,i,malloced);
  527. /*
  528.     Remember struct_destruct() DOESN'T take a 
  529.     parenthesized actualParams argument!
  530. */
  531.     else if (malloced)
  532.       structFncPrefix_free(thiS_0);
  533.     return (structType *) 0;
  534.   }
  535.  
  536.   return thiS_0;
  537. }
  538.  
  539. /*
  540.     If you have more than one constructor then
  541.     repeat the struct_init_def() definition above
  542.     with an overloaded suffix parameter and the
  543.     appropriate initialization parameters.
  544. */
  545.  
  546.  
  547.  
  548. /*
  549.     This protected destructor is called by the
  550.     public destructor macro.  It is also called
  551.     by the protected struct_init constructor in
  552.     the event of a failure to construct.  Thus
  553.     this destructor must be able to correctly
  554.     handle any partially constructed data that
  555.     may be handed off by the failing constructor!
  556. */
  557.  
  558. struct_destruct_def(structType,structFncPrefix)
  559. {
  560.   unsigned i;
  561.  
  562.   if (!thiS_0 || !nobj)
  563.     return;
  564.  
  565.   for (i = nobj; i--; /* no reinit */)  {
  566.  
  567. /*
  568.     Setup vFT and polymorphic virtual base
  569.     descendants for structType level.
  570.  
  571.     The vFT must be initialized exactly the same
  572.     way they were in struct_init_def() above!
  573. */
  574.     struct_initVFTs(structFncPrefix
  575.       ,(&thiS_0[i], (void *)0
  576.       , vFT0(structType)
  577.       , vFT0(base1StructType)
  578.     /* or vFT_value(structType,base1StructType) */
  579.       , vFT0(base11StructType)
  580.     /* or vFT_value(structType,base11StructType) */
  581.       , vFT0(base12StructType)
  582.     /* or vFT_value(structType,base12StructType) */
  583.       , vFT0(base2StructType)
  584.     /* or vFT_value(structType,base2StructType) */
  585.       , vbThiS_name(base3StructType)
  586.       , vbDescendanT_value(base3StructType,thiS)
  587.       , vFT0(base3StructType)
  588.     /* or vFT_value(structType,base3StructType) */
  589.       ));
  590. /* Be sure to have enough closing parentheses above! */
  591.  
  592.  
  593. /*
  594.     Destruct structType data here. Beware of 
  595.     partially constructed data handed off by a 
  596.     failing constructor!  This should never be
  597.     the case if you follow the form above in
  598.     struct_init_def() exactly.
  599. */
  600.  
  601.     thiS_0[i].???
  602.  
  603.  
  604.     /* destruct base struct data */
  605.  
  606.     struct_destruct(base3FncPrefix,
  607.         structFncPrefix_base3StructTypeThiS
  608.         (&thiS_0[i]),1,0);
  609. /*
  610.     Remember struct_destruct() DOESN'T take a 
  611.     parenthesized actualParams argument!
  612. */
  613.     struct_destruct(base2FncPrefix,
  614.         structFncPrefix_base2StructTypeThiS
  615.         (&thiS_0[i]),1,0);
  616. /*
  617.     Remember struct_destruct() DOESN'T take a 
  618.     parenthesized actualParams argument!
  619. */
  620.     struct_destruct(base1FncPrefix,
  621.         structFncPrefix_base1StructTypeThiS
  622.         (&thiS_0[i]),1,0);
  623. /*
  624.     Remember struct_destruct() DOESN'T take a 
  625.     parenthesized actualParams argument!
  626. */
  627.  
  628.  
  629.   }  /* for */
  630.  
  631.   if (malloced)
  632.     structFncPrefix_free(thiS_0);
  633. }
  634.  
  635.  
  636. /*
  637.     Define structType member functions below 
  638.     following their declaration order laid out
  639.     in the header file.
  640. */
  641.